﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Rules
{
    //移动和吃子
    public static class MoveAndEat
    {
        public static bool CanMoveTo(this Chessman chessman, Location target)
        {
            Square thisSquare = chessman.Square;
            Square targetSquare = ChessBoard.Get[target];
            //如果目标位置的坐标不合法，则不可通行
            if (!target.IsValid())
            {
                return false;
            }
            //如果目标位置是己方兽穴，则不可通行
            if (targetSquare.type == SquareType.Cave && targetSquare.camp == chessman.camp)
            {
                return false;
            }
            //如果目标位置是水域且当前棋子不是鼠，则不可通行
            if ((!chessman.IsRat) && targetSquare.type == SquareType.River)
            {
                return false;
            }

            //如果目标位置是自己的位置，则不可通行
            if (chessman.location == target)
            {
                return false;
            }
            //如果目标位置有自己的棋子或者敌方的不可攻击棋子，则不可通行
            if (targetSquare.Chessman != null)
            {
                //如果目标位置有本方棋子，则不可通行
                if (targetSquare.Chessman.camp == chessman.camp)
                {
                    return false;
                }
                //目标位置有敌方棋子时
                else
                {
                    //如果目标位置的敌方棋子强于自己，则不可通行
                    if (!chessman.CanEat(targetSquare.Chessman))
                    {
                        return false;
                    }
                    //如果鼠试图出水或者入水，则出入水的过程中不能吃子
                    if ((thisSquare.type == SquareType.River) != (targetSquare.type == SquareType.River))
                    {
                        return false;
                    }
                }
            }
            //如果目标位置不是可达点(距离为1格的点，或者狮虎跳河目标点)，则不可通行

            //当棋子不是狮虎时
            if (!chessman.CanJump)
            {
                //目标位置距离不为1，即可判定为不可到达
                if (!chessman.location.IsNear(target))
                {
                    //Debug.Log("I");
                    return false;
                }
            }
            //当棋子是狮虎时
            else
            {
                //目标位置的距离不为1，同时不是跳河目标时，判定为不可到达
                if (!chessman.location.IsNear(target) && (!thisSquare.RiverSide(targetSquare)))
                {
                    //Debug.Log("J");
                    return false;
                }
            }

            return true;
        }

        //吃子规则
        public static bool CanEat(this Chessman chessman, Chessman other)
        {
            //如果是同一方的子，则不可互吃
            if (chessman.camp == other.camp)
            {
                return false;
            }
            //如果是鼠vs象，则必定可吃
            if (chessman.IsRat && other.IsElephant)
            {
                return true;
            }
            //如果是象vs鼠，且鼠没有被困在陷阱内
            if (chessman.IsElephant && other.IsRat && (!other.IsTrapped))
            {
                return false;
            }
            return chessman.Attack >= other.Defence;
        }

        public static bool CanMove(this Chessman chessman)
        {
            for (int x = Location.Xmin; x <= Location.Xmax; x++)
            {
                for(int y = Location.Ymin; y <= Location.Ymax;y++)
                {
                    if(chessman.CanMoveTo(new Location(x,y)))
                    {
                        return true;
                    }
                }
            }
            return false;
        }
    }

    #region River
    public static class Square_RiverSupport
    {
        private static bool IsOnSameLine(this Square square, Square other)
        {
            Location a = square.location;
            Location b = other.location;
            if (a.Equals(b))
            {
                return false;
            }
            else
            {
                if (a.x == b.x || a.y == b.y)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }

        private static List<Square> GetBetweens(Square A, Square B)
        {
            List<Square> ret = new List<Square>();
            if (!A.IsOnSameLine(B))
            {
                return ret;
            }

            if (A.x == B.x)
            {
                int x = A.x;
                int ymin = Mathf.Min(A.y, B.y);
                int ymax = Mathf.Max(A.y, B.y);
                for (int y = ymin + 1; y < ymax; y++)
                {
                    Square between = ChessBoard.Get[x, y];
                    ret.Add(between);
                }
            }
            else if (A.y == B.y)
            {
                int y = A.y;
                int xmin = Mathf.Min(A.x, B.x);
                int xmax = Mathf.Max(A.x, B.x);
                for (int x = xmin + 1; x < xmax; x++)
                {
                    Square between = ChessBoard.Get[x, y];
                    ret.Add(between);
                }
            }
            return ret;
        }

        /// <summary>
        /// 判断两个棋盘格之间是否满足跳河条件。包含了位置判定和鼠的阻隔判定。
        /// </summary>
        public static bool RiverSide(this Square A, Square B)
        {
            var betweens = GetBetweens(A, B);
            if (betweens.Count != 0)
            {
                foreach (var between in betweens)
                {
                    if (between.type != SquareType.River)
                    {
                        return false;
                    }
                    if(between.Chessman != null)
                    {
                        return false;
                    }
                }
                return true;
            }
            return false;
        }
    }
    #endregion


    #region 终局判定
    public static class EndOfGame
    {
        /// <summary>
        /// 将死: 如果当前行棋的玩家的某个陷阱被敌方占领，且该玩家无法吃掉这个子，则当前行棋的玩家输了
        /// </summary>
        /// <returns></returns>
        public static bool IsCheckMateEnd()
        {
            foreach (var square in ChessBoard.Get.squares)
            {
                if (square.type != SquareType.Trap && square.type != SquareType.Cave)
                {
                    continue;
                }
                //如果兽穴已经被占领，则当前行棋的玩家输了
                if (square.type == SquareType.Cave && square.camp == PlayerManager.Get.currentPlayer && square.Chessman != null)
                {
                    Debug.Log("游戏结束: 兽穴被占领");
                    return true;
                }
                //判断"将死"的情形:如果一个陷阱已经被敌方占领，且能够解决此情况的己方棋子数为0，则当前行棋的玩家输了(被将死)
                if (square.type == SquareType.Trap && square.camp == PlayerManager.Get.currentPlayer && square.Chessman != null)
                {
                    if (square.Chessman.camp != square.camp)
                    {
                        List<Chessman> defenders = new List<Chessman>();
                        foreach (var defender in Chessman.All(PlayerManager.Get.currentPlayer))
                        {
                            if (defender.CanMoveTo(square.location))
                            {
                                defenders.Add(defender);
                                break;
                            }
                        }
                        if (defenders.Count == 0)
                        {
                            Debug.Log("游戏结束: 将死");
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 如果当前行棋的玩家失去了全部棋子，或者虽有棋子但所有棋子都无法移动，则当前行棋的玩家输了
        /// </summary>
        /// <returns></returns>
        public static bool IsEliminatedEnd()
        {
            var chessmenOfPlayer = Chessman.All(PlayerManager.Get.currentPlayer);
            foreach (var chessman in chessmenOfPlayer)
            {
                if (chessman.CanMove())
                {
                    return false;
                }
            }
            Debug.Log(chessmenOfPlayer.Count == 0 ? "游戏结束:全部消灭" : "游戏结束:困毙");
            return true;
        }
    }
    #endregion
}